package org.jsoft.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

/**
 * 图片工具类
 * @author szsw
 *
 */
public class ImageUtil {

	/**
	 * 透明色常量
	 */
	public static final int RGBA_TRANSPARENT = new Color(0,0,0,0).getRGB();
	
	/**
	 * 判断颜色是否相似
	 * @param cFir 第一个颜色
	 * @param cSec 第二个淹死
	 * @param range 模糊范围，如果传入小于0的数，将被赋值为0，没有模糊范围
	 * @return 如果相似返回true，不相似返回false
	 */
	private static boolean colorLike(Color cFir, Color cSec, int range){
		if(range < 0){
			range = 0;
		}
		int c1R = cFir.getRed();
		int c1G = cFir.getGreen();
		int c1B = cFir.getBlue();
		int c1A = cFir.getAlpha();
		int c2R = cSec.getRed();
		int c2G = cSec.getGreen();
		int c2B = cSec.getBlue();
		int c2A = cSec.getAlpha();
		
		boolean r = false;
		boolean g = false;
		boolean b = false;
		boolean a = false;
		
		if(c1R >= c2R - range && c1R <= c2R + range){
			r = true;
		}else{
			return false;
		}
		if(c1G >= c2G - range && c1G <= c2G + range){
			g = true;
		}else{
			return false;
		}
		if(c1B >= c2B - range && c1B <= c2B + range){
			b = true;
		}else{
			return false;
		}
		if(c1A >= c2A - range && c1A <= c2A + range){
			a = true;
		}else{
			return false;
		}
		
		if(r && g && b && a){
			return true;
		}else{
			return false;
		}
		
	}

	/**
	 * 通过字符串创建Color
	 * @param rgb 像素参数。RGB用逗号分隔，RGBA也用逗号分隔。例如：R,G,B  A,R,G,B
	 * @return 创建好的Color
	 */
	private static Color createColor(String rgb){
		String[] rgbArr = rgb.split(",");
		if(rgbArr.length == 4){
			int A = new Integer(rgbArr[0]);
			int R = new Integer(rgbArr[1]);
			int G = new Integer(rgbArr[2]);
			int B = new Integer(rgbArr[3]);
			return new Color(R, G, B, A);
		}else{
			int R = new Integer(rgbArr[0]);
			int G = new Integer(rgbArr[1]);
			int B = new Integer(rgbArr[2]);
			return new Color(R, G, B);
		}
	}
	
	public static String colorToString(Color color){
		if(color != null){
			return color.getAlpha() + "," + color.getRed() + "," + color.getGreen() + "," + color.getBlue();
		}else{
			return "0,0,0,0";
		}
	}
	
	/**
	 * 创建分割图片的集合
	 * @param img 目标图片
	 * @param row 共有几行
	 * @param column 每行多少列
	 * @return 返回分割好的图片集合
	 */
	public static List<BufferedImage> createImages(BufferedImage img, int row, int column){
		List<BufferedImage> result = new ArrayList<BufferedImage>();
		int w = img.getWidth() / column;
		int h = img.getHeight() / row;
		for(int j = 0; j < row; j++){
			for(int i = 0; i < column; i++){
				//设置了输出图片的大小
				BufferedImage i1 = new BufferedImage(w, h, img.getColorModel().getTransparency());
				Graphics2D g2 = i1.createGraphics();
				//目标图片，要截取图片的起始坐标0,0，要截取图片的结束坐标w,h，截取图片的起始坐标，截取图片的结束坐标
				g2.drawImage(img, 0, 0, w, h, w * i, h * j, w * (i + 1), h * (j + 1), null);
				g2.dispose();
				result.add(i1);
			}
		}
		return result;
	}
	
	/**
	 * 裁剪图片
	 * @param img 图片源
	 * @param x 要裁剪区域在图片源的X轴坐标
	 * @param y 要裁剪区域在图片源的Y轴坐标
	 * @param width 宽度
	 * @param height 高度
	 * @return 图片
	 */
	public static BufferedImage cutImage(BufferedImage img, int x, int y, int width, int height){
		BufferedImage result = new BufferedImage(width, height, img.getColorModel().getTransparency());
		Graphics2D g2 = result.createGraphics();
		g2.drawImage(img, 0, 0, width, height, x, y, x + width, y + height, null);
		g2.dispose();
		return result;
	}

	/**
	 * 创建分割图片的二维数组
	 * @param img 目标图片
	 * @param row 共有几行
	 * @param column 每行多少列
	 * @return 返回分割好的图片二维数组
	 */
	public static BufferedImage[][] createImagesArr(BufferedImage img, int row, int column){
		BufferedImage[][] result = new BufferedImage[row][column];
		List<BufferedImage> imgList = createImages(img, row, column);
		for(int i = 0; i < row; i++){
			for(int j = 0; j < column; j++){
				int index = i * column + j;
				result[i][j] = imgList.get(index);
			}
		}
		return result;
	}

	/**
	 * 翻转图像
	 * @param bufferedImage 目标图像
	 * @param isUpDown 是否是上下翻转。true为上下翻转，否则为左右翻转
	 * @return 返回处理后的图片
	 */
	public static BufferedImage flipImage(BufferedImage bufferedImage, boolean isUpDown) {
		int w = bufferedImage.getWidth();
		int h = bufferedImage.getHeight();
		BufferedImage img = new BufferedImage(w, h, bufferedImage.getColorModel().getTransparency());
		Graphics2D graphics2d = img.createGraphics();
		if(isUpDown){
			graphics2d.drawImage(bufferedImage, 0, 0, w, h, 0, h, w, 0, null);
		}else{
			graphics2d.drawImage(bufferedImage, 0, 0, w, h, w, 0, 0, h, null);
		}
		graphics2d.dispose();
		return img;
	}

	/**
	 * 获得图片
	 * @param path 图片路径
	 * @return 返回图片
	 */
	public static BufferedImage getImage(String path) {
		try {
			BufferedImage bi = ImageIO.read(new File(ImageUtil.class.getClassLoader().getResource(path).getFile()));
			if (bi != null) {
				bi.getWidth();
			}
			return bi;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	/**
	 * 获得图片组，要求图片在同一路径下，图片的名称从0开始，不能包含其他字符
	 * @param path 图片路径
	 * @param length 要加载的图片数量
	 * @return 返回图片组
	 */
	public static BufferedImage[] getImage(String path, int length) {
		return getImage(path, length, "png");
	}
	
	/**
	 * 获得图片组，要求图片在同一路径下，图片的名称从0开始，不能包含其他字符
	 * @param path 图片路径
	 * @param length 要加载的图片数量
	 * @param type 图片类型。例如：png、jpg等
	 * @return 返回图片组
	 */
	public static BufferedImage[] getImage(String path, int length, String type) {
		BufferedImage[] result = new BufferedImage[length];
		for (int i = 0; i < length; i++) {
				result[i] = ImageUtil.getImage(path + i + "." + type);
			if (result[i] != null) {
				result[i].getWidth();
			}
		}
		return result;
	}
	
	/**
	 * 获得图片组，要求图片在同一路径下，图片的名称从0开始，不能包含其他字符
	 * @param path 图片路径
	 * @param type 图片类型。例如：png、jpg等
	 * @return 返回图片组
	 */
	public static BufferedImage[] getImageArr(String path) {
		return getImageArr(path, "png");
	}
	
	/**
	 * 获得图片组，要求图片在同一路径下，图片的名称从0开始，不能包含其他字符
	 * @param path 图片路径
	 * @param length 要加载的图片数量
	 * @return 返回图片组
	 */
	public static BufferedImage[] getImageArr(String path, String type) {
		BufferedImage[] result = null;
		File dir = new File(ImageUtil.class.getClassLoader().getResource(path).getFile());
		if(dir.isDirectory()){
			result = getImage(path, dir.list().length, type);
		}else{
			result = new BufferedImage[1];
			result[0] = getImage(path);
		}
		return result;
	}
	
	/**
	 * 替换图片多种指定颜色
	 * @param bufferedImage 目标图像
	 * @param rgbMap 颜色键值对，key是要替换的原来的颜色，value是替换成新的颜色
	 * @return 返回处理后的图片
	 */
	public static BufferedImage replaceColor(BufferedImage bufferedImage, Map<String, String> rgbMap) {
		return replaceColorVague(bufferedImage, rgbMap, 0);
	}
	
	/**
	 * 替换图片指定颜色
	 * @param bufferedImage 目标图像
	 * @param oldRGB 要替换的原来的颜色
	 * @param newRGB 替换成新的颜色
	 * @return 返回处理后的图片
	 */
	public static BufferedImage replaceColor(BufferedImage bufferedImage, String oldRGB, String newRGB) {
		Map<String, String> rgbMap = new HashMap<String, String>();
		rgbMap.put(oldRGB, newRGB);
		return replaceColor(bufferedImage, rgbMap);
	}
	
	/**
	 * 模糊替换图片多种指定颜色
	 * @param bufferedImage 目标图像
	 * @param rgbMap 颜色键值对，key是要替换的原来的颜色，value是替换成新的颜色
	 * @param range 模糊范围，每个像素点加减这个值。如果传入小于0的数，那么将被赋值为0，没有模糊范围
	 * @return 返回处理后的图片
	 */
	public static BufferedImage replaceColorVague(BufferedImage bufferedImage, Map<String, String> rgbMap, int range) {
		//map为空时直接返回原图片，不为空做替换
		if(rgbMap != null && rgbMap.size() > 0){
			int w = bufferedImage.getWidth();
			int h = bufferedImage.getHeight();
			int type = bufferedImage.getColorModel().getTransparency();
			BufferedImage img = new BufferedImage(w, h, type);
			Graphics2D graphics2d = img.createGraphics();
			graphics2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
			List<Color> oldRGB = new ArrayList<Color>();
			List<Color> newRGB = new ArrayList<Color>();
			Iterator<Entry<String, String>> it = rgbMap.entrySet().iterator();
			while(it.hasNext()){
				Entry<String, String> e = it.next();
				Color old = createColor(e.getKey());
				oldRGB.add(old);
				Color n = createColor(e.getValue());
				newRGB.add(n);
				
			}
			for(int i = 0; i < h; i++){
				for(int j = 0; j < w; j++){
					for(int k = 0; k < oldRGB.size(); k++){
						//获得图片每个像素的RGB，将RGB转化成二进制，每8位表示一个颜色，第一个8位是透明度，第二个是R，第三个是G，第四个是B。例子：11111111 11111111 11111111 11111111
						if(colorLike(oldRGB.get(k), new Color(bufferedImage.getRGB(j, i), true), range)){
							//替换像素点颜色
							bufferedImage.setRGB(j, i, newRGB.get(k).getRGB());
						}
					}
				}
			}
			graphics2d.drawImage(bufferedImage, 0, 0, null);
			graphics2d.dispose();
			return img;
		}else{
			return bufferedImage;
		}
	}
	
	/**
	 * 模糊替换图片指定颜色
	 * @param bufferedImage 目标图像
	 * @param oldRGB 要替换的原来的颜色
	 * @param newRGB 替换成新的颜色
	 * @param range 模糊范围，每个像素点加减这个值。如果传入小于0的数，那么将被赋值为0，没有模糊范围
	 * @return 返回处理后的图片
	 */
	public static BufferedImage replaceColorVague(BufferedImage bufferedImage, String oldRGB, String newRGB, int range) {
		Map<String, String> rgbMap = new HashMap<String, String>();
		rgbMap.put(oldRGB, newRGB);
		return replaceColorVague(bufferedImage, rgbMap, range);
	}
	
	/**
	 * 旋转图片为指定角度
	 * @param bufferedimage 目标图像
	 * @param degree 旋转角度
	 * @return 返回处理后的图片
	 */
	public static BufferedImage rotateImage(BufferedImage bufferedimage, int degree) {
		int w = bufferedimage.getWidth();
		int h = bufferedimage.getHeight();
		int type = bufferedimage.getColorModel().getTransparency();
		BufferedImage img = new BufferedImage(w, h, type);
		Graphics2D graphics2d = img.createGraphics();
		graphics2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);
		graphics2d.drawImage(bufferedimage, 0, 0, null);
		graphics2d.dispose();
		return img;
	}
	
	/**
	 * 修改图片大小
	 * @param bufferedImage 目标图片
	 * @param width 修改后的宽度
	 * @param height 修改后的高度
	 * @return 修改完成的图片
	 */
	public static BufferedImage updateSize(BufferedImage bufferedImage, int width, int height) {
		BufferedImage img = new BufferedImage(width, height, bufferedImage.getColorModel().getTransparency());
		Graphics2D graphics2d = img.createGraphics();
		graphics2d.drawImage(bufferedImage, 0, 0, width, height, null);
		graphics2d.dispose();
		return img;
	}
	
	/**
	 * 创建透明像素图片
	 * @param width 图片宽度
	 * @param height 图片高度
	 * @return 创建好的图片
	 */
	public static BufferedImage createTransparentImage(int width, int height){
		return createImage(width, height, new Color(0, true));
	}
	
	/**
	 * 创建指定颜色的图片
	 * @param width 图片宽度
	 * @param height 图片高度
	 * @param color 颜色
	 * @return 创建好的图片
	 */
	public static BufferedImage createImage(int width, int height, Color color){
		BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics2d = img.createGraphics();
		graphics2d.setColor(color);
		graphics2d.drawImage(img, 0, 0, width, height, null);
		graphics2d.dispose();
		return img;
	}
	
	public static Toolkit tk = Toolkit.getDefaultToolkit();

	/**
	 * 创建GIF动态图片。动态图片需要
	 * @param path 图片地址
	 * @return GIF动态图片
	 */
	public static Image getImageGif(String path){
		Image img = tk.getImage(ImageUtil.class.getClassLoader().getResource(path));
		if(img != null){
			img.getWidth(null);
		}
		return img;
	}
	
	/**
	 * 图片合成
	 * 合成一个图片，背景色为fillColor，覆盖一个图片bgImg，继续覆盖图片coverImg
	 * @param bgImg 底层图片
	 * @param coverImg 上层图片
	 * @param fillColor 背景色
	 * @return 合成后的图片
	 */
	public static BufferedImage compositeImage(BufferedImage bgImg, BufferedImage coverImg, Color fillColor){
		int w = 0;
		int h = 0;
		if(bgImg != null){
			if(coverImg != null){
				w = bgImg.getWidth() > coverImg.getWidth() ? bgImg.getWidth() : coverImg.getWidth();
				h = bgImg.getHeight() > coverImg.getHeight() ? bgImg.getHeight() : coverImg.getHeight();
			}else{
				w = bgImg.getWidth();
				h = bgImg.getHeight();
			}
		}else{
			if(coverImg != null){
				w = coverImg.getWidth();
				h = coverImg.getHeight();
			}
		}
		BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = result.createGraphics();
		if(fillColor == null){
			fillColor = new Color(0, true);
		}
		g.setColor(fillColor);
		g.fillRect(0, 0, w, h);
		if(bgImg != null){
			int img1_x = (w - bgImg.getWidth()) / 2;
			int img1_y = (h - bgImg.getHeight()) / 2;
			g.drawImage(bgImg, img1_x, img1_y, null);
		}
		if(coverImg != null){
			int img2_x = (w - coverImg.getWidth()) / 2;
			int img2_y = (h - coverImg.getHeight()) / 2;
			g.drawImage(coverImg, img2_x, img2_y, null);
		}
		g.dispose();
		return result;
	}
	
}
